package org.ggumm21.moneybook;

import java.util.List;

import javax.persistence.Id;
import javax.persistence.Transient;

import org.codehaus.jackson.annotate.JsonIgnore;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.annotation.Cached;
import com.googlecode.objectify.annotation.Parent;

@Cached
public class AccountCategory {

	@Id private Long id;
	private String name;
	private int order;
	private Long upperCateId;
	
	@JsonIgnore
	@Parent 
	private Key<AccountCategoryType> cateTypeKey;
	
	@SuppressWarnings("unused")
	@Transient private String key;
	@SuppressWarnings("unused")
	@Transient private String upperKey;
	
	private AccountCategoryType.CATE_TYPE cateType;
	boolean isMinus;
	boolean isExpired;
	private boolean balDecrease;
		
	@SuppressWarnings("unused")
	@Transient private long cateTypeId; // Just for bean method getCateTypeId

	int subCategoryCount = 0;
	int itemCount = 0;
	public enum enumSubTotalViewMode {
	    VIEW_WITH_SUB_TOTAL, 
	    VIEW_WITHOUT_SUB_TOTAL,
	    VIEW_ONLY_SUB_TOTAL,
	    VIEW_NONE
	} ;
	enumSubTotalViewMode subTotalViewMode = enumSubTotalViewMode.VIEW_WITHOUT_SUB_TOTAL;;

	public boolean isMinus() {
		return isMinus;
	}
	
	public boolean isExpired() {
		return isExpired;
	}
	
	public boolean isBalDecrease() {
		return balDecrease;
	}

	public void setMinus(boolean isMinus) {
		this.isMinus = isMinus;
	}

	public void setExpired(boolean isExpired) {
		this.isExpired = isExpired;
	}

	public void increaseItemCount() {
		this.itemCount++;
	}

	public void decreaseItemCount() {
		this.itemCount--;
	}

	public boolean getHasItems() {
		return itemCount > 0;
	}

	public boolean getHasSubCategory() {
		return subCategoryCount > 0;
	}

	public void increaseSubCategoryCount() {
		this.subCategoryCount++;
	}

	public void decreaseSubCategoryCount() {
		this.subCategoryCount--;		
	}
	
	public void setSubTotalViewMode(enumSubTotalViewMode subTotalViewMode) {
		this.subTotalViewMode = subTotalViewMode;
	}

	public enumSubTotalViewMode getSubTotalViewMode() {
		return subTotalViewMode;
	}

	@SuppressWarnings("unused")
	private AccountCategory() {
	}
	
	public AccountCategory(AccountCategoryType cateType, String name, int order, long upperId) {
		this.cateTypeKey = new Key<AccountCategoryType>(AccountCategoryType.class, cateType.getId());
		this.name = name;
		this.order = order;
		this.upperCateId = upperId;
		this.balDecrease = cateType.isBalDecrease();
		this.subTotalViewMode = enumSubTotalViewMode.VIEW_WITH_SUB_TOTAL;
		this.cateType = cateType.getCategoryType();
	}
	
	public long getId() {
		return id;
	}
	
	public String getName() {
		return name;
	}

	public int getOrder() {
		return order;
	}

	public void setOrder(int order) {
		this.order = order;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public static Key<AccountCategory> getKey(long cateTypeId, long id) {
		return new Key<AccountCategory>(
					new Key<AccountCategoryType>(AccountCategoryType.class, cateTypeId)
					, AccountCategory.class, id);
	}

	public Long getUpperCategoryId() {
		return upperCateId;
	}
	
	@JsonIgnore
	public AccountCategory getUpperCategory() {
		if (upperCateId == null) return null;
		return ObjectifyService.begin().find(new Key<AccountCategory>(
													cateTypeKey, 
													AccountCategory.class, 
													upperCateId));
	}
	
	@JsonIgnore
	public List<AccountCategory> getSubCategories() {
		return ObjectifyService.begin().query(AccountCategory.class)
									.ancestor(cateTypeKey)
									.filter("upperCateId", id)
									.order("order")
								.list();
	}
	
	public static void getAllSubCategories(AccountCategory cate, List<AccountCategory> list) {
		
		List<AccountCategory> subList = ObjectifyService.begin()
											.query(AccountCategory.class)
												.ancestor(cate.cateTypeKey)
												.filter("upperCateId", cate.id)
												.order("order")
											.list();
		list.addAll(subList);
		for(AccountCategory subCate : subList) {
			getAllSubCategories(subCate, list);
		}
	}

	public int getSubCategoryCount() {
		return this.subCategoryCount;
	}
	
	public long getCateTypeId() {
		return cateTypeKey.getId();
	}
	
	public AccountCategoryType.CATE_TYPE getCateType() {
		return cateType;
	}

	public String getKey() {
		return getCateTypeId() + "-" + id;
	}
	
	public String getUpperKey() {
		return getCateTypeId() + "-" + upperCateId;
	}
	
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append(this.getClass().getName())
			.append(" : id=").append(id)
			.append(", name=[").append(cateType.getName())
					.append("|").append(name).append("]")
			.append(", upper=").append(upperCateId)
			.append(", expired=").append(isExpired)
			.append(", minus=").append(isMinus)
			;
		return sb.toString();		
	}
	
}
